<?php

namespace App\Kuafu\User\Service;

use App\Kuafu\User\Enum\UserCodeEnum;
use App\Kuafu\User\Model\UserFirstLoginModel;
use Illuminate\Support\Facades\Redis;

class NewUserService
{
    const NEW_USER_HASH = 'NEW_USER_HASH';

    private int    $userId;
    private string $hashKey;
    private string $hashField;
    private string $date;

    public function __construct(int $userId, string $date = '')
    {
        if (!$date) {
            $this->date = date('Ymd');
        } else {
            $this->date = date('Ymd', strtotime($date));
        }

        $this->userId    = $userId;
        $this->hashKey   = self::NEW_USER_HASH . ":" . $this->date;
        $this->hashField = $this->userId;

    }

    public function apiIn(): array
    {
        // 是否有今日hash
        if (Redis::hexists($this->hashKey, $this->userId)) {
            return [];
        }

        // 判断新用户
        $newUser = (int)UserFirstLoginModel::isUserFirstLogin($this->userId, UserCodeEnum::MERCHANT_TYPE);

        // 判断新用户次日留存
        $newNextRemain = 0;
        if (!$newUser) {

            // 查昨日是否为新用户
            $yesterday = strtotime($this->date . ' -1 day');

            $newNextRemain = (int)(bool)UserFirstLoginModel
                ::query()
                ->where('userId', $this->userId)
                ->whereBetween('createdAt', [$yesterday, $yesterday + 86399])
                ->count();
        }

        $value = ['newUser' => $newUser, 'newNextRemain' => $newNextRemain];

        Redis::hset($this->hashKey, $this->hashField, json_encode($value));

        return $value;
    }

    /**
     * 日活
     * @return int
     */
    public function dau(): int
    {
        return (int)Redis::hlen($this->hashKey);
    }

    /**
     * 新用户
     * @return int
     */
    public function newUser(): int
    {
        return UserFirstLoginModel
            ::query()
            ->whereBetween('createdAt', [strtotime($this->date), strtotime($this->date) + 86399])
            ->count();
    }

    /**
     * 新用户次日留存率
     * @return float
     */
    public function newNextRemainRate()
    {
        // 遍历hashKey
        $newNextRemain = 0;

        $alls = Redis::hgetall($this->hashKey);
        foreach ($alls as $all) {
            $all = json_decode($all, true);
            if (isset($all['newNextRemain']) && $all['newNextRemain']) {
                $newNextRemain++;
            }
        }

        // 前一天的新用户
        $yesterday = date('Ymd', strtotime($this->date . ' -1 day'));
        $yesterdayNewUser = (new self(0, $yesterday))->newUser();

        if ($yesterdayNewUser <= 0) {
            return 0;
        }

        return round($newNextRemain / $yesterdayNewUser * 100, 2);
    }
}
